// web-server.js
const fs = require('fs');
const http = require('http');
const WebSocket = require('ws');
const url = require('url');
const path = require('path');
const express = require('express');
const cors = require('cors');

const corsOptions = {
    origin: 'http://localhost:5173',
    optionsSuccessStatus: 200
};

class WebServer {
    constructor(app, port) {
        this.app = app;
        this.port = port;
        this.expressApp = express();
        this.server = http.createServer(this.expressApp);
        this.wss = new WebSocket.Server({ server: this.server });
        this.userDataPath = app.userDataPath;
        this.expressApp.use(cors(corsOptions));
        this.expressApp.use(express.json());

        // 存储活动 WebSocket 连接的 Map
        this.connections = new Set();
        this.ws_connections = new Map();
    }

    // 初始化web server的路由
    _initHttpServer() {
        const handlersPath = path.join(__dirname, 'ipcHandlers');
        const topLevelDirs = fs.readdirSync(handlersPath);

        for (let i = 0; i < topLevelDirs.length; i++) {
            let topLevelDir = topLevelDirs[i];
            const topLevelDirPath = path.join(handlersPath, topLevelDir);
            if (fs.statSync(topLevelDirPath).isDirectory()) {
                const handlerFiles = fs.readdirSync(topLevelDirPath);
                for (let j = 0; j < handlerFiles.length; j++) {
                    let file = handlerFiles[j];
                    if (file.endsWith('.js')) {
                        const handlerClass = require(path.join(topLevelDirPath, file));
                        const handler = new handlerClass(this.app);
                        const eventName = `/${path.basename(file, '.js')}`;
                        // console.log(`Register WebServer Route: [${eventName}]`);
                        this.expressApp.use(eventName, async (req, resp) => {
                            let params = {};
                            if (req.method == 'GET') {
                                // console.log(`\t[LocalServer${eventName}] req.query:`, JSON.stringify(req.query) + '\n');
                                params = req.query;
                            } else if (req.method == 'POST') {
                                // console.log(`\t[LocalServer${eventName}] req.body:`, JSON.stringify(req.body) + '\n');
                                params = req.body;
                            }

                            let event = {
                                from: 'localserver',
                                resp: resp
                            };
                            await handler.handle(event, params);
                            // console.log(result);
                            // resp.send(result);
                        });
                    }
                }
            }
        }
    }

    // 初始化web socket服务
    _initWebSocket() {
        this.wss.on('connection', (ws, req) => {
            const queryObject = url.parse(req.url, true).query;
            const pageId = queryObject.uuid;

            if (pageId) {
                if (this.ws_connections.has(pageId)) {
                    console.log(`WebSocket connection for page ${pageId} already exists.`);
                    // ws.close();
                    return;
                }

                console.log('## WebSocket connection established for page:', pageId);
                this.ws_connections.set(pageId, ws);

                ws.on('message', (message) => {
                    console.log(`Received from ${pageId}:`, message);
                    // ws.send(`Received your message: ${message}`);
                });

                ws.on('close', () => {
                    console.log('## WebSocket connection closed for page:', pageId);
                    if (this.ws_connections.get(pageId) === ws) {
                        this.ws_connections.delete(pageId);
                    }
                });

                ws.on('error', (error) => {
                    console.error('WebSocket error:', error);
                });
            } else {
                ws.close();
                console.error('Connection rejected: UUID is required');
            }
        });
    }

    // 发送消息到页面
    sendToPage(pageId, msg) {
        if (this.ws_connections.has(pageId) == false) {
            console.log(`## PageId ${pageId} not found`);
            return false;
        }

        let ws = this.ws_connections.get(pageId);
        ws.send(msg);
        return true;
    }

    // 广播消息到所有页面
    broadcast(msg) {
        this.ws_connections.forEach((ws, pageId) => {
            ws.send(msg);
        });
    }

    // 开始监听
    async start() {
        this._initHttpServer();
        this._initWebSocket();

        // 启动本地server并进行必要的异常处理判断
        return new Promise((resolve, reject) => {
            this.server
                .listen(this.port)
                .on('listening', () => {
                    console.log(`## Open LocalServer & WebSocket OK [http://localhost:${this.port}]`);
                    resolve();
                })
                .on('connection', (conn) => {
                    // console.log('connection from http server!');
                    this.connections.add(conn);
                    conn.on('close', () => {
                        this.connections.delete(conn);
                    });
                })
                .on('error', (error) => {
                    console.error('## Open Local Server Failed, Error:', error);
                    reject(error);
                });
        });
    }

    // 关闭web socket服务
    _closeWebSocket() {
        return new Promise((resolve, reject) => {
            this.wss.clients.forEach((client) => {
                client.terminate();
            });

            this.wss.close((error) => {
                if (error) {
                    console.error('## Close WebSocket Server Failed, Error =', error);
                    reject(error);
                } else {
                    console.log('## Close WebSocket Server OK!');
                    resolve();
                }
            });
        });
    }

    _closeHttpServer() {
        return new Promise((resolve, reject) => {
            // 关闭http server服务
            for (let conn of this.connections) {
                conn.destroy();
            }

            this.server.close((error) => {
                if (error) {
                    console.log('## Close Local Server Failed, Error =', error);
                    reject(error);
                } else {
                    console.log('## Close Local Http Server OK!');
                    resolve();
                }
            });
        });
    }

    // 关闭所有服务
    async close() {
        // 关闭web socket服务
        try {
            await this._closeWebSocket();
            await this._closeHttpServer();
        } catch (error) {
            console.error('## Error during closing servers:', error);
            throw error;
        }
    }
}

module.exports = { WebServer };
